package com.alks.function.service.impl.finance.ryfinance;

import com.alks.common.aop.AutoPageAop;
import com.alks.common.data.dto.SysUserTokenDTO;
import com.alks.common.data.thread.UserIdThread;
import com.alks.common.service.RedisService;
import com.alks.common.utils.beanutils.ArrayUtils;
import com.alks.common.utils.beanutils.BeanUtil;
import com.alks.entity.data.entity.PcCostDetail;
import com.alks.entity.data.entity.PcCostTemp;
import com.alks.entity.data.entity.PcOrderHead;
import com.alks.entity.data.entity.YfCostDetail;
import com.alks.entity.data.response.ResponseInfo;
import com.alks.entity.exception.ServiceErrorException;
import com.alks.function.data.dto.finance.ryfinance.CostDetailDto;
import com.alks.function.data.request.finance.ryfinance.*;
import com.alks.function.data.vo.finance.ryfinance.TempToDetVo;
import com.alks.function.mapper.PcOrderHeadMapping;
import com.alks.function.mapper.common.BackMapper;
import com.alks.function.mapper.finance.ryfinance.PcCostTempMapper;
import com.alks.function.mapper.finance.ryfinance.YfCostDetailMapper;
import com.alks.function.service.finance.ryfinance.IBillFessService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.Page;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.temporal.Temporal;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

import static com.alks.common.utils.beanutils.StringUtils.convertToUpper;
import static com.alks.entity.data.enums.ResultCodeEnum.INPUT_ERROR;

/**
 * 财务部-荣阳财务-费用结算作业
 *
 * @author MS
 */
@Service
@Slf4j
public class BillFessServiceImpl extends ServiceImpl<PcCostTempMapper, PcCostTemp> implements IBillFessService {
    @Autowired
    private PcCostTempMapper tempMapper;
    @Autowired
    private YfCostDetailMapper detailMapper;
    @Autowired
    private PcOrderHeadMapping ordMapping;
    @Autowired
    private RedisService redisService;
    @Autowired
    private BackMapper backMapper;

    private final String kk = "扣款";

    @Override
    public ResponseInfo costTempQuery() {
        SysUserTokenDTO tokenDTO = UserIdThread.get();
        String companyId = tokenDTO.getCompanyId();
        String loginName = tokenDTO.getLoginName();
        /*获取数据*/
        List<PcCostTemp> dtos = lambdaQuery()
                .eq(PcCostTemp::getCompanyId, companyId)
                .eq(PcCostTemp::getSysUser, loginName)
                .orderByDesc(PcCostTemp::getItem).list();
        /*求金额之和*/
        BigDecimal amtSum = dtos.stream().map(PcCostTemp::getAmt).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
        BigDecimal qtySum = dtos.stream().map(PcCostTemp::getQty).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
        /*封装数据*/
        Map<String, Object> map = new HashMap<>(3);
        map.put("dtos", dtos);
        map.put("amtSum", amtSum);
        map.put("qtySum", qtySum);
        return ResponseInfo.ok(map);
    }

    @Override
    public ResponseInfo costTempAdd(PcCostTemp request) {
        SysUserTokenDTO tokenDTO = UserIdThread.get();
        String companyId = tokenDTO.getCompanyId();
        String loginName = tokenDTO.getLoginName();
        /*判断指令是否存在*/
        if (StringUtils.isNotBlank(request.getLotNo())) {
            LambdaQueryWrapper<PcOrderHead> ordWrapper = new LambdaQueryWrapper<PcOrderHead>()
                    .eq(PcOrderHead::getCompanyId, companyId)
                    .eq(PcOrderHead::getOrderId, request.getLotNo());
            if (ordMapping.selectCount(ordWrapper) <= 0) {
                log.error("\n错误接口：costTempAdd\n错误原因：尝试写入不存在的指令：{}", request.getLotNo());
                return ResponseInfo.error("指令不存在", INPUT_ERROR.getCode());
            }
        }
        /*获取item*/
        List<PcCostTemp> temps = lambdaQuery()
                .eq(PcCostTemp::getCompanyId, companyId)
                .eq(PcCostTemp::getSysUser, loginName).list();
        BigDecimal item = temps.stream()
                .map(PcCostTemp::getItem)
                .filter(Objects::nonNull)
                .reduce((max, current) -> (max.compareTo(current) >= 0) ? max : current)
                .map(max -> max.add(BigDecimal.ONE))
                /*设置默认值为1*/
                .orElse(BigDecimal.ZERO.add(BigDecimal.ONE));
        request.setCompanyId(companyId);
        request.setItem(item);
        request.setSysUser(loginName);
        /*写入数据*/
        tempMapper.insert(request);
        return ResponseInfo.ok();
    }

    @Override
    public void costTempUpdate(PcCostTemp request) {
        SysUserTokenDTO tokenDTO = UserIdThread.get();
        String companyId = tokenDTO.getCompanyId();
        String loginName = tokenDTO.getLoginName();
        /*如果没有ITEM则新增*/
        if (request.getItem()==null){
            costTempAdd(request);
        }else {
            /*更新数据*/
            lambdaUpdate()
                    .eq(PcCostTemp::getCompanyId, companyId)
                    .eq(PcCostTemp::getSysUser, loginName)
                    .eq(PcCostTemp::getItem, request.getItem())
                    .set(PcCostTemp::getLotNo, request.getLotNo())
                    .set(PcCostTemp::getCostDesc, request.getCostDesc())
                    .set(PcCostTemp::getQty, request.getQty())
                    .set(PcCostTemp::getPrice, request.getPrice())
                    .set(PcCostTemp::getAmt, request.getAmt())
                    .set(PcCostTemp::getCostUnit, request.getCostUnit())
                    .set(PcCostTemp::getRemark, request.getRemark()).update();
        }
    }

    @Override
    public ResponseInfo costTempDelete(Integer item) {
        SysUserTokenDTO tokenDTO = UserIdThread.get();
        String companyId = tokenDTO.getCompanyId();
        String loginName = tokenDTO.getLoginName();
        /*删除数据*/
        LambdaQueryWrapper<PcCostTemp> wrapper = new LambdaQueryWrapper<PcCostTemp>()
                .eq(PcCostTemp::getCompanyId, companyId)
                .eq(PcCostTemp::getSysUser, loginName)
                .eq(PcCostTemp::getItem, item);
        PcCostTemp pcCostTemp = tempMapper.selectOne(wrapper);
        /*处理扣款事件*/
        if (pcCostTemp != null && kk.equals(pcCostTemp.getFeeStatus())){
            statusCancel(companyId, pcCostTemp.getFeeSlipNo(),pcCostTemp.getFeeItem());
        }
        tempMapper.delete(wrapper);
        return ResponseInfo.ok();
    }

    /**
     * 去除扣款标志
     * @param slipNo 待去扣款标志订单号
     * @param item 待去扣款标志订单内序号
     */
    private void statusCancel(String companyId, String slipNo, BigDecimal item) {
        /*检测是否还有其他扣款项*/
        LambdaQueryWrapper<YfCostDetail> detailWrapper = new LambdaQueryWrapper<YfCostDetail>()
                .eq(YfCostDetail::getCompanyId, companyId)
                .eq(YfCostDetail::getCbSlipNo, slipNo)
                .eq(YfCostDetail::getCbItem, item);
        if (detailMapper.selectCount(detailWrapper).equals(0)) {
            /*如果没有则删除扣款标志*/
            LambdaUpdateWrapper<YfCostDetail> detailUpWrapper = new LambdaUpdateWrapper<YfCostDetail>()
                    .set(YfCostDetail::getProcessStatus, null)
                    .eq(YfCostDetail::getCompanyId, companyId)
                    .eq(YfCostDetail::getSlipNo, slipNo)
                    .eq(YfCostDetail::getItem, item);
            detailMapper.update(null, detailUpWrapper);
        }
    }

    @Override
    @AutoPageAop
    public Map<String, Object> costDetailQuery(CostDetailQueryRequest request) {
        String companyId = UserIdThread.get().getCompanyId();
        int asc = 1;
        int desc = 2;
        /*获取数据*/
        LambdaQueryWrapper<YfCostDetail> wrapper = new LambdaQueryWrapper<YfCostDetail>()
                .eq(YfCostDetail::getCompanyId, companyId)
                .like(!BeanUtil.stringIsEmpty(request.getSlipNo()), YfCostDetail::getSlipNo, request.getSlipNo())
                .ge(request.getSlipDateStart() != null, YfCostDetail::getSlipDate, request.getSlipDateStart())
                .le(request.getSlipDateEnd() != null, YfCostDetail::getSlipDate, request.getSlipDateEnd())
                .like(!BeanUtil.stringIsEmpty(request.getTypeName()), YfCostDetail::getTypeName, request.getTypeName())
                .like(!BeanUtil.stringIsEmpty(request.getVendorName()), YfCostDetail::getVendorName, request.getVendorName())
                .ge(request.getSysDateStart() != null, YfCostDetail::getSysDate, request.getSysDateStart())
                .le(request.getSysDateEnd() != null, YfCostDetail::getSysDate, request.getSysDateEnd())
                .like(!BeanUtil.stringIsEmpty(request.getLotNo()), YfCostDetail::getLotNo, request.getLotNo())
                .like(!BeanUtil.stringIsEmpty(request.getFinanceYymm()), YfCostDetail::getFinanceYymm, request.getFinanceYymm())
                .like(!BeanUtil.stringIsEmpty(request.getCostDesc()), YfCostDetail::getCostDesc, request.getCostDesc())
                .like(!BeanUtil.stringIsEmpty(request.getBalanceNo()), YfCostDetail::getBalanceNo, request.getBalanceNo())
                .like(!BeanUtil.stringIsEmpty(request.getSendNo()), YfCostDetail::getSendNo, request.getSendNo())
                .isNull(request.getFlag() != null && request.getFlag().equals(1), YfCostDetail::getCfmFlag)
                .eq(request.getFlag() != null && (request.getFlag().equals(2) || request.getFlag().equals(3)), YfCostDetail::getCfmFlag, "Y")
                .isNull(request.getFlag() != null && request.getFlag().equals(3), YfCostDetail::getBalanceNo)
                .isNotNull(request.getFlag() != null && request.getFlag().equals(4), YfCostDetail::getBalanceNo);
        //做排序
        if (request.getOrderFlag() != null && request.getOrderFlag().equals(asc) && !BeanUtil.allIsEmpty(request.getOrderName())) {
            String orderName = convertToUpper(request.getOrderName());
            wrapper.last("ORDER BY " + orderName);
        } else if (request.getOrderFlag() != null && request.getOrderFlag().equals(desc) && !BeanUtil.allIsEmpty(request.getOrderName())) {
            String orderName = convertToUpper(request.getOrderName());
            wrapper.last("ORDER BY " + orderName + " DESC");
        } else {
            wrapper.last("ORDER BY SLIP_NO DESC,ITEM ASC");
        }
        List<YfCostDetail> details = detailMapper.selectList(wrapper);
        /*获取页数*/
        List<CostDetailDto> dtos = BeanUtil.copyList(details, CostDetailDto.class);
        /*补全指令数*/
        List<String> lotNos = dtos.stream()
                .map(CostDetailDto::getLotNo)
                .collect(Collectors.toList());
        LambdaQueryWrapper<PcOrderHead> headMapper = new LambdaQueryWrapper<PcOrderHead>()
                .select(PcOrderHead::getOrderId, PcOrderHead::getOrderQty)
                .eq(PcOrderHead::getCompanyId, companyId)
                .in(PcOrderHead::getOrderId, lotNos);
        List<PcOrderHead> heads = ordMapping.selectList(headMapper);
        Map<String, BigDecimal> qtyMaps = heads.stream()
                .collect(Collectors.toMap(PcOrderHead::getOrderId, PcOrderHead::getOrderQty));
        dtos.forEach(a -> a.setOrderQty(qtyMaps.get(a.getLotNo())));
        wrapper.select(YfCostDetail::getAmt, YfCostDetail::getSendNo);
        /*封装数据*/
        Map<String, Object> map = new HashMap<>(4);
        /*计算求和数据*/
        List<YfCostDetail> details1 = detailMapper.selectList(wrapper);
        BigDecimal amtSum = details1.stream().map(YfCostDetail::getAmt).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
        BigDecimal qtySum = details1.stream().map(YfCostDetail::getQty).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
        map.put("dtos", dtos);
        map.put("amtSum", amtSum);
        map.put("qtySum", qtySum);
        if (!request.getPageSize().equals(-1)&& !request.getPageNum().equals(-1)) {
            Page<YfCostDetail> page = (Page<YfCostDetail>) details;
            map.put("total", page.getTotal());
        }
        return map;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResponseInfo costTempToDetail(CostTempToDetailRequest request) {
        SysUserTokenDTO tokenDTO = UserIdThread.get();
        String loginName = tokenDTO.getLoginName();
        String userName = tokenDTO.getUserName();
        String companyId = tokenDTO.getCompanyId();
        /*入参检测*/
        String vendorNo = backMapper.getVendorNoByName(request.getVendorName());
        if (BeanUtil.allIsEmpty(vendorNo)) {
            log.warn("\n异常接口：costTempToDetail\n异常原因：不存在的厂商\n入参：{}", request.getVendorName());
            return ResponseInfo.error("厂商不存在", INPUT_ERROR.getCode());
        }
        List<Map<String, String>> costType = backMapper.getPcCostType(null, request.getTypeName(), companyId);
        if (ArrayUtils.isEmpyt(costType)) {
            log.warn("\n异常接口：costTempToDetail\n异常原因：不存在的费用类型\n入参：{}", request.getVendorName());
            return ResponseInfo.error("费用类型不存在", INPUT_ERROR.getCode());
        }
        /*获取数据*/
        List<TempToDetVo> detVos = tempMapper.getDetailQuery(companyId, loginName);
        if (ArrayUtils.isEmpyt(detVos)){
            return ResponseInfo.ok();
        }
        /*处理扣款*/
        if ("扣款".equals(request.getTypeName())){
            for (TempToDetVo detVo : detVos) {
                if (detVo.getAmt().compareTo(BigDecimal.ZERO)>0){
                    throw new ServiceErrorException("扣款金额不能大于0");
                }
            }
        }
        /*检验数据完整性*/
        for (TempToDetVo vo : detVos) {
            if (vo.getLotNo() == null) {
                log.warn("\n异常接口：costTempToDetail\n异常原因：存在lotNo为null的元素\n异常表：【PC_COST_TEMP】");
                return ResponseInfo.error("指令不能为空", INPUT_ERROR.getCode());
            }
            LambdaQueryWrapper<PcOrderHead> wrapper = new LambdaQueryWrapper<PcOrderHead>()
                    .eq(PcOrderHead::getOrderId, vo.getLotNo())
                    .eq(PcOrderHead::getCompanyId, companyId);
            PcOrderHead head = ordMapping.selectOne(wrapper);
            if (head == null) {
                log.warn("\n异常接口：costTempToDetail\n异常原因：orderId不存在\n传入参数：{}", vo.getLotNo());
                return ResponseInfo.error("指令" + vo.getLotNo() + "不存在", INPUT_ERROR.getCode());
            }
        }
        /*获取订单号*/
        String slipNo = detVos.stream()
                .filter(a -> "修改".equals(a.getFeeStatus()))
                .map(TempToDetVo::getSlipNo).findAny()
                .orElse(redisService.slipNoCreat("", "RSF", 5));
        /*补充数据*/
        LocalDate slipDate = request.getSlipDate() == null ? LocalDate.now() : request.getSlipDate();
        for (TempToDetVo vo : detVos) {
            YfCostDetail detail = BeanUtil.copyBean(vo, YfCostDetail.class);
            detail.setSysUser(userName);
            detail.setSysDate(LocalDateTime.now());
            detail.setSlipDate(slipDate);
            detail.setVendorName(request.getVendorName());
            detail.setVendorNo(vendorNo);
            detail.setTypeName(request.getTypeName());
            detail.setTypeNo(costType.get(0).get("typeNo"));
            detail.setSendNo(request.getSendNo());
            detail.setCompanyId(companyId);
            detail.setSlipNo(slipNo);
            if ("扣款".equals(vo.getFeeStatus())) {
                detail.setCbSlipNo(vo.getSlipNo());
                detail.setCbItem(vo.getFeeItem());
            }
            /*写入数据*/
            detailMapper.insert(detail);

            /*补充扣款字段*/
            List<TempToDetVo> kkVoList = detVos.stream().filter(a -> "扣款".equals(a.getFeeStatus())).collect(Collectors.toList());
            if (ArrayUtils.isNoEmpyt(kkVoList)) {
                for (TempToDetVo kkVo : kkVoList) {
                    LambdaQueryWrapper<YfCostDetail> wrapper = new LambdaQueryWrapper<YfCostDetail>()
                            .eq(YfCostDetail::getCompanyId,companyId)
                            .eq(YfCostDetail::getSlipNo, kkVo.getSlipNo())
                            .eq(YfCostDetail::getItem, kkVo.getFeeItem())
                            .eq(YfCostDetail::getProcessStatus,"扣款");
                    detailMapper.update(null,wrapper);
                }
            }
        }
        /*删除上表数据*/
        LambdaQueryWrapper<PcCostTemp> tempWrapper = new LambdaQueryWrapper<PcCostTemp>()
                .eq(PcCostTemp::getCompanyId, companyId)
                .eq(PcCostTemp::getSysUser, loginName);
        tempMapper.delete(tempWrapper);
        return ResponseInfo.ok();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResponseInfo costDetailToTemp(List<CostDTTRequest> request, Integer type) {
        SysUserTokenDTO tokenDTO = UserIdThread.get();
        String loginName = tokenDTO.getLoginName();
        String companyId = tokenDTO.getCompanyId();
        /*获取detail数据*/
        List<PcCostTemp> temps;
        if (type.equals(1)) {
            /*处理修改情况*/
            temps = modifyQuery(request, loginName, companyId);
        } else {
            /*处理扣款情况*/
            temps = chargeBackQuery(request, loginName, companyId);
        }
        /*写入数据*/
        if (!ArrayUtils.isEmpyt(temps)) {
            temps.forEach(tempMapper::insert);
        } else {
            log.warn("\n异常接口：costDetailToTemp\n异常原因：没有找到数据\n表名：【YF_COST_DETAIL】 传参:{}", request);
            throw new ServiceErrorException("数据异常");
        }
        return ResponseInfo.ok();
    }

    /**
     * 处理扣款情况的数据修改和查询
     *
     * @param request   定位数据
     * @param loginName 用户英文名
     * @param companyId 公司ID
     * @return 待写入数据
     */
    @Transactional(rollbackFor = Exception.class)
    @NotNull
    public List<PcCostTemp> chargeBackQuery(List<CostDTTRequest> request, String loginName, String companyId) {
        List<PcCostTemp> temps = detailMapper.chargeBackQuery(request, loginName, companyId);
        /*获取序号并写入*/
        BigDecimal itemMax = lambdaQuery()
                .select(PcCostTemp::getItem)
                .eq(PcCostTemp::getCompanyId, companyId)
                .eq(PcCostTemp::getSysUser, loginName).list()
                .stream().map(PcCostTemp::getItem)
                .max(BigDecimal::compareTo)
                .orElse(BigDecimal.ZERO)
                .add(BigDecimal.ONE);
        for (PcCostTemp temp : temps) {
            temp.setItem(itemMax);
            itemMax = itemMax.add(BigDecimal.ONE);
        }
        return temps;
    }

    /**
     * 修改按钮对应获取数据修改和查询
     *
     * @param request   传入数据
     * @param loginName 用户英文名
     * @param companyId 公司ID
     * @return temps
     */
    @Transactional(rollbackFor = Exception.class)
    @NotNull
    public List<PcCostTemp> modifyQuery(List<CostDTTRequest> request, String loginName, String companyId) {
        /*判断是否有扣款*/
        for (CostDTTRequest r : request) {
            chargeBackCheck(r.getSlipNo(), r.getItem());
        }
        /*获取需要的数据*/
        List<String> slipNoList = request.stream()
                .map(CostDTTRequest::getSlipNo)
                .collect(Collectors.toList());
        List<PcCostTemp> temps = detailMapper.modifyQuery(request, loginName, companyId);
        /*写入序号*/
        for (int i = 0; i < temps.size(); i++) {
            temps.get(i).setItem(BigDecimal.valueOf(i));
            temps.get(i).setFeeStatus("修改");
        }
        /*修改需要删除以前的数据*/
        LambdaQueryWrapper<PcCostTemp> tempWrapper = new LambdaQueryWrapper<PcCostTemp>()
                .eq(PcCostTemp::getSysUser, loginName)
                .eq(PcCostTemp::getCompanyId, companyId);
        tempMapper.delete(tempWrapper);
        /*删除detail表里的数据*/
        LambdaQueryWrapper<YfCostDetail> detailWrapper = new LambdaQueryWrapper<YfCostDetail>()
                .eq(YfCostDetail::getCompanyId, companyId)
                .in(YfCostDetail::getSlipNo, slipNoList);
        detailMapper.delete(detailWrapper);
        return temps;
    }

    @Override
    public ResponseInfo costDetailUpdate(List<CostDetUpRequest> request, Integer financeType, String financeYymm) {
        SysUserTokenDTO tokenDTO = UserIdThread.get();
        String userName = tokenDTO.getUserName();
        String companyId = tokenDTO.getCompanyId();
        /*数据定位部分*/
        LambdaUpdateWrapper<YfCostDetail> wrapper = new LambdaUpdateWrapper<YfCostDetail>()
                .eq(YfCostDetail::getCompanyId, companyId)
                .and(a -> {
                    final boolean[] first = {true};
                    request.forEach(b -> {
                        if (first[0]) {
                            a.eq(YfCostDetail::getItem, b.getItem())
                                    .eq(YfCostDetail::getSlipNo, b.getSlipNo());
                            first[0] = false;
                        } else {
                            a.or().eq(YfCostDetail::getItem, b.getItem())
                                    .eq(YfCostDetail::getSlipNo, b.getSlipNo());
                        }
                    });
                    return a;
                });
        if (financeType == null) {
            wrapper.set(YfCostDetail::getRemarkCw, request.get(0));
        } else if (financeType.equals(1)) {
            /*结算处理*/
            finance(financeYymm, wrapper, userName);
        } else {
            /*取消结算处理*/
            cancelFinance(wrapper);
        }
        /*修改数据*/
        detailMapper.update(null, wrapper);
        return ResponseInfo.ok();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResponseInfo costDetailDelete(String slipNo, BigDecimal item) {
        SysUserTokenDTO tokenDTO = UserIdThread.get();
        String companyId = tokenDTO.getCompanyId();
        /*扣款有关处理*/
        chargeBackCheck(slipNo, item);
        LambdaUpdateWrapper<YfCostDetail> wrapper = new LambdaUpdateWrapper<YfCostDetail>()
                .eq(YfCostDetail::getCompanyId, companyId)
                .eq(YfCostDetail::getSlipNo, slipNo)
                .eq(YfCostDetail::getItem, item);
        List<YfCostDetail> details = detailMapper.selectList(wrapper);
        /*删除数据*/
        detailMapper.delete(wrapper);
        return ResponseInfo.ok();
    }

    /**
     * 结算处理
     * @param financeYymm 结算年月
     * @param wrapper     定位数据
     * @param userName    操作人
     */
    private void finance(String financeYymm, LambdaUpdateWrapper<YfCostDetail> wrapper, String userName) {
        /*检核月份输入是否正确*/
        RecTbAccountServiceImpl.financeDateCheck(financeYymm);
        /*检测是否存在已结算*/
        List<YfCostDetail> details = detailMapper.selectList(wrapper);
        for (YfCostDetail detail : details) {
            if (detail.getCfmFlag() != null && "Y".equals(detail.getCfmFlag())) {
                log.warn("\n异常接口：costDetailUpdate\n异常原因：结算了已经结算的数据\n对应数据：{}", detail);
                throw new ServiceErrorException("存在已结算数据，单据号码：" + detail.getSlipNo());
            }
        }
        /*补充数据修改*/
        wrapper.set(YfCostDetail::getFinanceYymm, financeYymm)
                .set(YfCostDetail::getCfmFlag, "Y")
                .set(YfCostDetail::getCfmUser, userName)
                .set(YfCostDetail::getCfmDate, LocalDate.now());
    }

    /**
     * 取消结算处理
     *
     * @param wrapper 数据定位
     */
    private void cancelFinance(LambdaUpdateWrapper<YfCostDetail> wrapper) {
        /*检测是否存在未结算*/
        List<YfCostDetail> details = detailMapper.selectList(wrapper);
        for (YfCostDetail detail : details) {
            if (detail.getCfmFlag() == null || !"Y".equals(detail.getCfmFlag())) {
                log.warn("\n异常接口：costDetailUpdate\n异常原因：取消结算了未结算的数据\n对应数据：{}", detail);
                throw new ServiceErrorException("存在未结算数据，单据号码：" + detail.getSlipNo());
            }
            if (detail.getBalanceNo() != null) {
                log.warn("\n异常接口：costDetailUpdate\n异常原因：取消结算了已应付的数据\n对应数据：{}", detail);
                throw new ServiceErrorException("存在已应付数据，单据号码：" + detail.getSlipNo());
            }
        }
        /*补充数据修改*/
        wrapper.set(YfCostDetail::getFinanceYymm, null)
                .set(YfCostDetail::getCfmFlag, null)
                .set(YfCostDetail::getCfmUser, null)
                .set(YfCostDetail::getCfmDate, null);
    }

    /**
     * 方案一：检测是否存在扣款记录（redis检测）
     *
     * @param slipNo 单据号
     */
    private void chargeBackCheck(String slipNo, BigDecimal item) {
        String status = "扣款";
        /*处理为备注*/
        String companyId = UserIdThread.get().getCompanyId();
        LambdaQueryWrapper<YfCostDetail> wrapper = new LambdaQueryWrapper<YfCostDetail>()
                .eq(YfCostDetail::getCbSlipNo, slipNo)
                .eq(YfCostDetail::getCbItem, item)
                .eq(YfCostDetail::getProcessStatus, status)
                .eq(YfCostDetail::getCompanyId, companyId);
        if (detailMapper.selectCount(wrapper) > 0) {
            throw new ServiceErrorException("存在扣款记录");
        }
    }
}
